Add detail_level and max_flows to get_affected_flows (fixes #849) - #853
Merged
tirth8205 merged 2 commits intoAug 19, 2026
Merged
Conversation
get_affected_flows_tool was the only tool in the review chain without detail_level, and it had no result bound. Every flow carries a full steps list, so a 75-file change set returned a 247k-token response in the middle of the documented minimal-first workflow. detail_level="minimal" strips flows to per-flow metadata (name, criticality, depth, counts). max_flows bounds the list (default 50, 0 disables); total always reports the untruncated count and truncated flags the cut, mirroring the impact-radius truncation contract. Fixes tirth8205#849
code-review-graph reviewOverall risk: 0.54 (MEDIUM) — 6 changed function(s)/class(es), 0 affected flow(s), 3 test gap(s) Risk-scored changes
Test gaps
Token savings: this graph-backed report used ~37,860 fewer tokens (~96%) than reading every changed file in full (estimated, chars/4 approximation). Powered by code-review-graph — local-first analysis; no code leaves the CI runner. |
Owner
|
Matches the sibling tool conventions and the truncation contract, and the 60 flow default cap case checks out. Merging. Follow-up noted in #866: the no changed files early return in tools/review.py omits the new truncated key. |
This was referenced Aug 19, 2026
TFSebben
pushed a commit
to TFSebben/code-review-graph
that referenced
this pull request
Aug 19, 2026
tirth8205#849 found get_affected_flows returning ~247k tokens inside a workflow documented as "5 tool calls, 800 tokens total". PR tirth8205#853 capped that one tool. Measuring all 30 registered tools against a real 5.6k-node graph found the same class of bug in ten more places, several of them on the default path: list_communities 206,858 tokens with DEFAULT arguments get_community 134,781 default / 535,618 with members get_architecture_overview 625,012 in standard mode refactor dead_code 47,312 / suggest 38,246 detect_changes 46,089 for a ONE-file diff get_surprising_connections 1,287,174 at top_n=10**6 get_hub_nodes 555,848 / get_bridge_nodes 317,202 get_review_context 4,720,622 on a whole-repo diff PR tirth8205#853's own fix was also only half a fix: standard mode carries a full steps list per flow (~980 tokens each), so its 50-flow cap still produced ~49k tokens, and max_flows=0 disabled the limit entirely. Every list-returning tool now follows one contract, the one tirth8205#853 established: `total` (or a per-list `*_total`) always reports the untruncated count, `truncated` marks the cut, and the summary line says how many of how many are shown. Bounds are validated the way query.py validates max_results - booleans rejected, values below 1 rejected. detail_level="minimal" was added to the analysis and refactor tools, projecting to the same compact field sets their siblings use. Where a count alone cannot bound a response, a shared budget does: get_flow and get_affected_flows spend a step budget, get_review_context and detect_changes spend a source-line budget. Ceilings that depend on payload size depend on detail_level, mirroring query.py capping minimal-mode results at five. Two behaviour changes are deliberate and their tirth8205#853 tests are updated in this commit: get_affected_flows standard mode now caps at 25 flows (minimal at 500), and max_flows=0 keeps its "no caller limit" meaning while still obeying the ceiling - an escape hatch that returns a quarter of a million tokens is the bug, not a feature. Default behaviour stays backward compatible in shape: an existing caller passing nothing still gets a valid response, just bounded. tests/test_token_budget.py records the measured budget table as reviewable data and pins it three ways: per-tool default and worst-case token ceilings, exact truncated list lengths against the imported ceiling constants, and the ceiling constants themselves. Removing a cap, raising a ceiling, or adding an unbounded field fails it. The fixture graph builds once per module and the whole file runs in ~7s, offline. Reported, not fixed: code_review_graph/tools/query.py is owned elsewhere and four of its tools remain unbounded - get_impact_radius (3.4M tokens; changed_nodes and edges ignore max_results, which is not even exposed on the MCP signature), find_large_functions (737k), traverse_graph (385k) and semantic_search_nodes, whose limit/token_budget are neither validated nor capped. Their default budgets are still asserted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012fHfGDiZedoxjpKzanHri3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #849
Problem
get_affected_flows_toolis step 2 of the documented review-pr workflow with its <=800-token target, but it was the only tool in the chain withoutdetail_leveland had no result bound. Each flow embeds a fullstepslist, so a 75-file change set produced a 247k-token response.Change
detail_level="minimal": per-flow metadata only (id, name, criticality, depth, node_count, file_count), same convention as the sibling tools.max_flows(default 50, 0 disables): bounds the returned list.totalalways reports the untruncated count andtruncatedflags the cut, mirroring the impact-radius truncation contract. The summary appends "showing N" when truncated.Both parameters are wired through the MCP tool wrapper with updated docstrings.
Tests
Three new tests: minimal drops steps/path, max_flows truncates with correct total/truncated/summary, max_flows=0 disables the limit. Full suite 2,401 passed, ruff and mypy clean.